<?php

namespace Application;

use Exception;
use SmartyBC;
use Zend_Auth;
use Zend_Form;
use Zend_View;

require_once('Smarty/SmartyBC.class.php');

abstract class ControllerAbstract
{
    protected $config;
    /** @var \Zend\Mvc\Router\RouteMatch $routeMatch */
    protected $routeMatch;
    /** @var \Application\Request $request */
    protected $request;

    abstract protected function getConfig();

    public function __construct()
    {
        $this->config = Config::getInstance();
        $this->request = Request::getInstance();
        $this->routePath = (string) substr(str_replace(
            $this->request->getBaseUrl(),
            '',
            parse_url($this->request->getRequestUri(), PHP_URL_PATH)
        ), 1);
    }

    public function setRouteMatch(\Zend\Mvc\Router\RouteMatch $routeMatch)
    {
        $this->routeMatch = $routeMatch;
    }

    public function callAction($action)
    {
        $method = $action . 'Action';
        if (!method_exists($this, $method)) {
            throw new Exception('Invalid controller action ' . $action);
        }
        if (false === ($result = $this->$method())) {
            return;
        }
        $result['baseUri'] = $this->request->getBaseUrl();
        $page = [];
        if (is_array($result)) {
            $this->getSmarty()->assign($result);
        }
        $page['bodyHtml'] = $this->getSmarty()->fetch($action . '.tpl');
        $auth = Zend_Auth::getInstance();
        if (!$auth->hasIdentity()) {
            $this->initMenu('mainMenu');
        } else {
            $this->initMenu('adminMainMenu');
            $this->getSmarty()->assign('loginName', $auth->getIdentity()->userName);
        }
        $this->getSmarty()->assign($page);
        $this->getSmarty()->assign('baseUri', $this->request->getBaseUrl());
        echo $this->getSmarty()->fetch($this->config['paths']['layout']);
    }

    protected function initMenu($menuName)
    {
        $menu = [];
        foreach ($this->config['modules'] as $module) {
            $moduleConfig = include($this->config['paths']['module'] . '/' . $module . '/config/module.config.php');
            if ($moduleConfig && array_key_exists($menuName, $moduleConfig)) {
                $menu = array_merge($menu, $moduleConfig[$menuName]);
            }
        }
        foreach ($menu as &$item) {
            $this->initMenuItem($item);
        }
        $this->getSmarty()->assign('mainMenu', $menu);

        return $this;
    }

    private function initMenuItem(&$item)
    {
        $item['active'] = ($item['alias'] == $this->routePath)
                || (
                    (0 !== strpos($this->routePath, 'admin'))
                    && (empty($item['alias']) ?  '' : 0 === strpos($this->routePath, $item['alias']))
                );
        if (!empty($item['items'])) {
            foreach ($item['items'] as &$sumItem) {
                $this->initMenuItem($sumItem);
            }
        }
        return $this;
    }

    protected function getSmarty()
    {
        static $smarty;
        if (null === $smarty) {
            $smarty = new SmartyBC();
            $smarty->setTemplateDir($this->getConfig()['templatePath']);
            $smarty->setCacheDir($this->config['paths']['smarty']['cache']);
            $smarty->setCompileDir($this->config['paths']['smarty']['compile']);
            $smarty->setConfigDir($this->config['paths']['smarty']['config']);
        }
        return $smarty;
    }

    public function notFoundAction($page)
    {
        echo $this->getSmarty()->assign('page', $page)->fetch($this->config['paths']['error404']);
        return $this;
    }

    public function redirect($url)
    {
        header('Location: ' . $this->request->getBaseUrl() . '/' . $url);
        exit;
    }

    protected function isValidForm(Zend_Form $form)
    {
        if ($this->request->isPost() && $form->isValid($this->request->getPost()->toArray())) {
            return true;
        }
        return false;
    }

    protected function getForm($formName)
    {
        /** @var Zend_Form $form */
        $formName .= 'Form';
        $form = new $formName($this->routeMatch);
        $form->setView(new Zend_View());
        $form->setAction($this->request->getRequestUri());
        return $form;
    }
}
